在 NodeJS 的時候,要建立一個網頁我們時常會搭配像是 Express、Koa、Hapi 這些框架,說到學習一個語言,最先開始的一定是 ,那小編今天就要來撰寫 Restful API,搭配的框架是 oak,它是目前 star 數最高的套件,相信有玩 Koa 的朋友跟這套件應該很熟悉,關於 oak 官方的介紹,我們在這裡也列給大家:
A middleware framework for Deno's http server, including a router middleware.
This middleware framework is inspired by Koa and middleware router inspired by koa-router.
是的,oak 它的靈感就是來自於 Koa,以及 Koa-router。
避免有些讀者並不知道 Koa,我們會大概提一下 Koa 的架構,然後就進入實作 Restful API。
Koa 是基於 NodeJS 的 HTTP 框架,是由 Express 原班人馬打造的,Koa2 使用的 async/ await 來做異步開發,與 Express 最大的不同是 Express 是漸進式的,也就是中間件一個接續一個執行;而 Koa 則因為中間件支持 generator,所以它的執行順序是洋蔥式的。
洋蔥式: 當從中間件開始執行,遇到 next 會進入下一個中間件,一直執行到最後一個中間件;順序相反時,則是執行上一個 next 之後的程式,一直執行到第一個中間件才發出響應。
那因為 oak 跟 koa 實在太像,接下來我們就直接帶實作拉~~~~
這裏我們將介紹如何使用 Oak 來開發一個 Restful API,他將支援以下功能:
事情預告:如果還沒安裝好環境的朋友,請先到前一天安裝好環境唷!!
// 第一次執行 Deno 會訪問這網址並安裝好 oak
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
const port = 8080;
const router = new Router(); // 宣告一個新路由
router.get("/", ({ response }: { response: any }) => {
response.body = {
message: "Hello World",
};
});
app.use(router.routes());
app.use(router.allowedMethods());
await app.listen({ port }); // 將跑在 127.0.0.1:8080 唷
當建立好了,使用 $ deno run --allow-net server.ts
就能將專案起起來囉~~ Hello World
這裏的 router.get會接收兩個參數,第一個是 路徑
,第二個是函數
,這裏我們宣告 response:any,代表 response 這個變量可以是 any 型,與就是避免掉 Typescript 的嚴格檢查,而 response.body 則是回傳的內容。 app.use(router.routes()) 是在說明要使用 router 變數中所有的路徑,app.use(router.allowedMethods()) 則是在說允許訪問的方法(Get, Post, Put, Delete等)。
3.新建 controllers 資料夾,並建立 todo.ts:
最後才會來撰寫 controller 這些方法唷,但是先定義起來
export default {
getAllTodos: () => {}, // 顯示 Todo
createTodo: async () => {}, // 新增 Todo
getTodoById: () => {}, // 顯示單筆 Todo
updateTodoById: async () => {}, // 修改 Todo
deleteTodoById: () => {}, // 刪除 Todo
}
import { Router } from "https://deno.land/x/oak/mod.ts";
const router = new Router();
// 引入剛剛建立在 controller 裡的方法
import todoController from "../controllers/todo.ts";
router
.get("/todos", todoController.getAllTodos)
.post("/todos", todoController.createTodo)
.get("/todos/:id", todoController.getTodoById)
.put("/todos/:id", todoController.updateTodoById)
.delete("/todos/:id", todoController.deleteTodoById);
export default router;
刪除
部分在 server.ts 裡的程式,並且使用剛剛引入的 router:引入 router
import todoRouter from './routes/routes.js';
刪除程式:
// 這一段是要刪除的唷
const router = new Router();
router.get("/", ({ response }: { response: any }) => {
response.body = {
message: "Hello World",
};
});
app.use(router.routes());
app.use(router.allowedMethods());
// 這一段是要刪除的唷
使用剛剛引入的 router (名稱為: todoRouter)
app.use(todoRouter.routes());
app.use(todoRouter.allowedMethods());
app.addEventListener("listen", ({ secure, hostname, port }) => {
const protocol = secure ? "https://" : "http://";
const url = ${protocol}${hostname ?? "localhost"}:${port};
console.log(Listening on: ${port});
});
export default interface Todo {
id: string,
todo: string,
isCompleted: boolean,
}
這裏的介面是為了約束使用者傳進來的資料格式
import { v4 } from 'https://deno.land/std/uuid/mod.ts';
import Todo from '../interfaces/Todo.ts';
let todos: Todo[] = [
{
id: v4.generate(), // 自動產生 string 的 id
todo: 'walk dog',
isCompleted: true,
},
{
id: v4.generate(),
todo: 'eat food',
isCompleted: false,
},
{
id: '3',
todo: 'eat food',
isCompleted: false,
},
];
export default todos;